package com.turman.plyopengl

import android.content.Context
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import android.opengl.Matrix
import androidx.compose.ui.graphics.Color
import com.turman.plyopengl.objects.Mallet
import com.turman.plyopengl.objects.Puck
import com.turman.plyopengl.objects.Table
import com.turman.plyopengl.programs.ColorShaderProgram
import com.turman.plyopengl.programs.TextShaderProgram
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class SampleRenderer3(private val context: Context) : GLSurfaceView.Renderer {
    /**
     * 透视投影矩阵
     */
    private val projectionMatrix: FloatArray = FloatArray(16)

    /**
     * 模型矩阵
     */
    private val modelMatrix = FloatArray(16)

    private val viewMatrix = FloatArray(16)
    private val viewProjectionMatrix = FloatArray(16)
    private val modelViewProjectionMatrix = FloatArray(16)


    private lateinit var table: Table
    private lateinit var mallet: Mallet
    private lateinit var puck: Puck

    private lateinit var textureShaderProgram: TextShaderProgram
    private lateinit var colorShaderProgram: ColorShaderProgram

    private var texture: Int = 0

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        // 设置Clear颜色
        GLES20.glClearColor(0F, 0F, 0F, 0F)

        table = Table()
        mallet = Mallet(0.08f, 0.15f, 32)
        puck = Puck(0.06f, 0.02f, 32)

        textureShaderProgram = TextShaderProgram(context)
        colorShaderProgram = ColorShaderProgram(context)

        texture = context.loadTexture(R.drawable.air_hockey_surface)
    }


    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES20.glViewport(0, 0, width, height)
        MatrixHelper.prespectiveM(
            projectionMatrix,
            55f,
            width.toFloat() / height.toFloat(),
            1f,
            10f
        )

        //创建一个视图矩阵
        Matrix.setLookAtM(viewMatrix, 0, 0f, 1.2f, 2.2f, 0f, 0f, 0f, 0f, 1f, 0f)

        //将模型矩阵设置为欸单位矩阵，然后沿着z轴平移量-2.5。
        Matrix.setIdentityM(modelMatrix, 0)
        //平移
        Matrix.translateM(modelMatrix, 0, 0f, 0f, -2.5f)
        //旋转,绕x轴旋转60
        Matrix.rotateM(modelMatrix, 0, -60f, 1f, 0f, 0f)

        //将模型矩阵和投影矩阵相乘获得最终的变换矩阵
        val temp = FloatArray(16)
        Matrix.multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0)
        System.arraycopy(temp, 0, projectionMatrix, 0, temp.size)
    }

    override fun onDrawFrame(gl: GL10?) {
        // 清除之前绘制的内容
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
        //这里将viewmatrix视图矩阵添加到绘制计算，使得场景中的物体随着视角（摄像头）的方向变化而旋转位移
        Matrix.multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0)

        positionTableInScene()
        textureShaderProgram.useProgram()
        textureShaderProgram.setUniforms(modelViewProjectionMatrix, texture)
        table.bindData(textureShaderProgram)
        table.draw()
        // 绘制Mallet
        positionObjectInScene(0F, mallet.height / 2F, -0.4F)
        colorShaderProgram.useProgram()
        colorShaderProgram.setUniforms(modelViewProjectionMatrix, Color(1f, 0f, 0f))
        mallet.bindData(colorShaderProgram)
        mallet.draw()

        positionObjectInScene(0F, mallet.height / 2F, 0.4F)
        colorShaderProgram.setUniforms(modelViewProjectionMatrix, Color(0f, 0f, 1f))
        // 请注意，我们不必两次定义对象数据，我们只要指定不同的位置，使用不同的颜色。
        mallet.draw()
        // 绘制Puck
        positionObjectInScene(0F, puck.height / 2F, 0F)
        colorShaderProgram.setUniforms(modelViewProjectionMatrix, Color(0.8f, 0.8f, 1f))
        puck.bindData(colorShaderProgram)
        puck.draw()

    }

    private fun positionTableInScene() {
        Matrix.setIdentityM(modelMatrix, 0)
        // 这张桌子是用X、Y坐标定义的，所以我们把它旋转90度，使它平放在xoz平面上
        Matrix.rotateM(modelMatrix, 0, -90f, 1f, 0f, 0f)
        Matrix.multiplyMM(
            modelViewProjectionMatrix, 0, viewProjectionMatrix,
            0, modelMatrix, 0
        )
    }

    private fun positionObjectInScene(x: Float, y: Float, z: Float) {
        Matrix.setIdentityM(modelMatrix, 0)
        Matrix.translateM(modelMatrix, 0, x, y, z)
        Matrix.multiplyMM(
            modelViewProjectionMatrix, 0, viewProjectionMatrix,
            0, modelMatrix, 0
        )
    }

}